﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Planning.Classes;
using Microsoft.VisualBasic.PowerPacks;

namespace Planning.Forms
{
    public partial class planningForm : Form
    {
        #region construct
        private string[] joursEn = new string[7] { "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday" };
        private string[] moisAnnee = new string[12] { "Janvier", "Février", "Mars", "Avril", "Mai", "Juin", "Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre" };
        public DataTable collectionFormation = new DataTable();

        public DateTime currentDate;
        public DateTime firstDay;
        public DateTime lastDay;
        public int nbJours;

        public bool isAdmin;
        public bool isVisiteur;
        public DataRow infoConnexion;

        public planningForm()
        {
            InitializeComponent();
            // Valorisation des membres
            this.isVisiteur = true;
            this.isAdmin = false;

            // On prépare les champs de la collection nécessaire pour la gestion d'evenement
            this.collectionFormation.Columns.Add("formation", typeof(RectangleShape));
            this.collectionFormation.Columns.Add("id_formation", typeof(int));

            // On cache à un invité les élément de l'utilisateur
            this.groupAction.Visible = false;
            this.groupBox1.Visible = false;
            this.groupBox2.Visible = false;

            // Préparation des élément de data du calendrier
            this.currentDate = DateTime.Now; // Date du jours
            this.nbJours = DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month); // Nb jour dans le mois
            this.firstDay = new DateTime(this.currentDate.Year, this.currentDate.Month, 1); // Premier jour du mois
            this.lastDay = new DateTime(this.currentDate.Year, this.currentDate.Month, DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month), 23, 59, 59, 999); // Dernier jour du mois

            // Label du mois et de l'année
            this.labelMois.Text = moisAnnee[this.currentDate.Month - 1];
            this.labelAnnee.Text = this.currentDate.Year.ToString();

            // Appel de la génération du calendrier
            generateCalendar(nbJours, this.firstDay, this.currentDate);
        }

        public planningForm(DataRow infoConnexion)
        {
            InitializeComponent();
            // Valorisation des membres
            this.infoConnexion = infoConnexion;
            this.isAdmin = (bool)infoConnexion["isSuperviseur"];
            this.isVisiteur = false;

            // On prépare les champs de la collection nécessaire pour la gestion d'evenement
            this.collectionFormation.Columns.Add("formation", typeof(RectangleShape));
            this.collectionFormation.Columns.Add("id_formation", typeof(int));

            // remplissage du cartouche utilisateur
            this.labelNom.Text = this.infoConnexion["nom_adherent"].ToString();
            this.labelPrenom.Text = this.infoConnexion["prenom_adherent"].ToString();
            this.labelMail.Text = this.infoConnexion["mail_adherent"].ToString();

            // Remplissage du cartouche association
            this.labelNomAssoc.Text = this.infoConnexion["nom_association"].ToString();
            this.labelAssocL2.Text = this.infoConnexion["adrl1_association"].ToString() + " , " + this.infoConnexion["cp_association"].ToString() + " , " + this.infoConnexion["ville_association"].ToString();

            // Gestion de l'affichage des actions pour les admin
            if (!isAdmin)
            {
                this.groupAction.Visible = false;
            }

            // Préparation des élément de data du calendrier
            this.currentDate = DateTime.Now; // Date du jours
            this.nbJours = DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month); // Nb jour dans le mois
            this.firstDay = new DateTime(this.currentDate.Year, this.currentDate.Month, 1); // Premier jour du mois
            this.lastDay = new DateTime(this.currentDate.Year, this.currentDate.Month, DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month), 23, 59, 59, 999); // Dernier jour du mois

            // Label du mois et de l'année
            this.labelMois.Text = moisAnnee[this.currentDate.Month - 1];
            this.labelAnnee.Text = this.currentDate.Year.ToString();

            // Génération du calendrier
            generateCalendar(nbJours, this.firstDay, this.currentDate);
        }
        #endregion

        #region generation_calendrier
        // Vide la collection de formation pour forcer l'actualisation
        public void cleanCalendar()
        {
            for (int i = collectionFormation.Rows.Count - 1; i >= 0; i--)
            {
                RectangleShape temp = (RectangleShape)collectionFormation.Rows[i]["formation"];
                collectionFormation.Rows[i].Delete();
                temp.Dispose();
            }
            for (int i = panelCalendrier.Controls.Count - 1; i >= 0; i--)
            {
                this.panelCalendrier.Controls[i].Dispose();
            }
        }

        // Methode générant le calendrier
        // @param nbJours = le nombre de jours dans le mois
        // @param firstDay = le premier  jours dans le mois
        // @param date = date acutel
        public void generateCalendar(int nbJours, DateTime firstDay, DateTime date)
        {
            int ligne = 0;
            int colonne = 0;
            int nextIndex = 0; // Le prochain index dans la collection de formation

            // 
            DataTable reqForm;
            if (isVisiteur) {
                reqForm = SQL.requete("SELECT id_formation, libelle_formation, CONVERT(VARCHAR(10), debut_formation, 103) as debut, nbFormations " +
                   "FROM FORMATION " +
                   "LEFT JOIN ( " +
                       "SELECT CONVERT(VARCHAR(10), debut_formation, 103) as theDate, COUNT(CONVERT(VARCHAR(10), debut_formation, 103)) as nbFormations " +
                       "FROM FORMATION " +
                       "GROUP BY CONVERT(VARCHAR(10), debut_formation, 103)" +
                   ") as q2 ON CAST(debut_formation as date) = q2.theDate " +
                   "WHERE debut_formation BETWEEN CONVERT(datetime, '" + this.firstDay.ToString("yyyy-MM-dd hh:mm:ss:fff") + "', 21) " +
                       "AND CONVERT(datetime, '" + this.lastDay.ToString("yyyy-MM-dd hh:mm:ss:fff") + "',21) " +
                   "ORDER BY debut_formation;");
            }
            else {
                reqForm = SQL.requete("SELECT id_formation, libelle_formation, CONVERT(VARCHAR(10), debut_formation, 103) as debut, nbFormations " +
                   "FROM FORMATION " +
                   "LEFT JOIN ( " +
                       "SELECT CONVERT(VARCHAR(10), debut_formation, 103) as theDate, COUNT(CONVERT(VARCHAR(10), debut_formation, 103)) as nbFormations " +
                       "FROM FORMATION " +
                       "GROUP BY CONVERT(VARCHAR(10), debut_formation, 103)" +
                   ") as q2 ON CAST(debut_formation as date) = q2.theDate " +
                   "WHERE debut_formation BETWEEN CONVERT(datetime, '" + this.firstDay.ToString("yyyy-MM-dd hh:mm:ss:fff") + "', 21) " +
                       "AND CONVERT(datetime, '" + this.lastDay.ToString("yyyy-MM-dd hh:mm:ss:fff") + "',21) " +
                   "AND id_association = " + infoConnexion["id_association"].ToString() + " " +
                   "ORDER BY debut_formation;");
            }
            // Gestion du premier jours dans le mois
            for (int i = 0; i < joursEn.Length; i++)
            {
                // Si le jours actuel du tableau = le premier jours alors on debute ici
                if (firstDay.DayOfWeek.ToString() == joursEn[i].ToString())
                {
                    colonne = i;
                }
            }

            // Création de tout les jours du mois
            for (int i = 0; i < nbJours; i++)
            {
                // Création du jours qu'on essaye de créer
                DateTime currentDay = new DateTime(date.Year, date.Month, i + 1);
                int nb = 0;

                // On compare le jours actuel avec le prochain index du tableau des formation
                if (nextIndex < reqForm.Rows.Count)
                {
                    // On convertie les datetime pour ne garder que la partie date
                    string convCurrentDay = currentDay.ToString().Substring(0, 10);
                    string convNextForm = reqForm.Rows[nextIndex]["debut"].ToString();
                    
                    Label labelForm = new Label();
                    labelForm.Text = "";
                    labelForm.AutoSize = true;

                    // Si ce jour est un jours de formation
                    if (convCurrentDay == convNextForm)
                    {
                        // Nombre de formation dans la journée
                        nb = Convert.ToInt32(reqForm.Rows[nextIndex]["nbFormations"].ToString());
                        // Si une seule formation
                        if (nb == 1)
                        {
                            labelForm.Text += reqForm.Rows[nextIndex]["libelle_formation"].ToString().Substring(0, 18);
                            labelForm.BackColor = Color.FromArgb(20, 0, 88, 117);
                            labelForm.TabIndex = 0;

                            // Positionnelement du label
                            labelForm.Top = Properties.Settings.Default.formationInitialX + 30 + Properties.Settings.Default.formationHauteur * ligne;
                            labelForm.Left = 7 + Properties.Settings.Default.formationLargeur * colonne + Properties.Settings.Default.largeurSeparation;
                            this.panelCalendrier.Controls.Add(labelForm);
                            // MessageBox.Show(reqForm.Rows[nextIndex]["id_formation"].ToString());
                            if (nextIndex < reqForm.Rows.Count) {
                                labelForm.Click += new EventHandler((sender, e) => label_Click(sender, e, currentDay));
                            }
                            generationFormation(currentDay, ligne, colonne, Convert.ToInt32(reqForm.Rows[nextIndex]["id_formation"]));
                            nextIndex++;

                        }
                        else
                        {
                            for (int j = nextIndex; j < nextIndex + nb; j++)
                            {
                                labelForm.Text += reqForm.Rows[j]["libelle_formation"].ToString().Substring(0, 18) + "\n";
                                labelForm.BackColor = Color.FromArgb(20, 0, 88, 117);
                                labelForm.TabIndex = 0;

                                // Positionnelement du label
                                labelForm.Top = Properties.Settings.Default.formationInitialX + 30 + Properties.Settings.Default.formationHauteur * ligne;
                                labelForm.Left = 7 + Properties.Settings.Default.formationLargeur * colonne + Properties.Settings.Default.largeurSeparation;

                                
                            }
                            this.panelCalendrier.Controls.Add(labelForm);
                            labelForm.Click += new EventHandler((sender, e) => formation_Click(sender, e, currentDay));

                            generationFormation(currentDay, ligne, colonne);
                            nextIndex = nextIndex + nb;
                        }
                    }
                }

                // Création du label du jour
                Label labelDay = new Label();
                labelDay.Text = (i + 1).ToString();
                labelDay.BackColor = Color.Transparent;
                labelDay.TabIndex = 1;


                // Gestion du retours à la ligne du dimanche
                if (currentDay.DayOfWeek.ToString() == "Sunday")
                {
                    // Positionnelement du label
                    labelDay.Top = Properties.Settings.Default.formationInitialX + 10 + Properties.Settings.Default.formationHauteur * ligne;
                    labelDay.Left = 10 + Properties.Settings.Default.formationLargeur * colonne + Properties.Settings.Default.largeurSeparation;
                    ligne++;
                    colonne = 0;
                }
                else
                {
                    // Positionnelement du label
                    labelDay.Top = Properties.Settings.Default.formationInitialX + 10 + Properties.Settings.Default.formationHauteur * ligne;
                    labelDay.Left = 10 + Properties.Settings.Default.formationLargeur * colonne + Properties.Settings.Default.largeurSeparation;
                    colonne++;
                }
                // Si une formation ce jours affichage du libelle
               

                // Ajout des label au panel
                this.panelCalendrier.Controls.Add(labelDay);

            }
        }
        #endregion

        #region generationFormation

        public void generationFormation(DateTime date, int ligne, int colonne)
        {
            // Création du container et du rectangle de la formation
            ShapeContainer container = new ShapeContainer();
            RectangleShape formation = new RectangleShape();

            //Defini le container du container du rectangle
            container.Parent = this.panelCalendrier;
            // Defini le container de la formation
            formation.Parent = container;

            // Definition du style de la formation
            formation.BackStyle = BackStyle.Opaque;
            formation.Left = Properties.Settings.Default.formationInitialY + Properties.Settings.Default.formationLargeur * colonne + Properties.Settings.Default.largeurSeparation * colonne;
            formation.Top = Properties.Settings.Default.formationInitialX + Properties.Settings.Default.formationHauteur * ligne;
            formation.Width = Properties.Settings.Default.formationLargeur;
            formation.Height = Properties.Settings.Default.formationHauteur;
            formation.BackColor = Color.FromArgb(20, 0, 88, 117);


            // Ajout de la formation a la collection
            this.collectionFormation.Rows.Add(formation, 0);

            // Evenement dynamique acceptant des paramatre en plus
            container.Click += new EventHandler((sender, e) => formation_Click(sender, e, date));

        }

        public void generationFormation(DateTime date, int ligne, int colonne, int idFormation)
        {
            // Création du container et du rectangle de la formation
            ShapeContainer container = new ShapeContainer();
            RectangleShape formation = new RectangleShape();

            //Defini le container du container du rectangle
            container.Parent = this.panelCalendrier;
            // Defini le container de la formation
            formation.Parent = container;

            // Definition du style de la formation
            formation.BackStyle = BackStyle.Opaque;
            formation.Left = Properties.Settings.Default.formationInitialY + (Properties.Settings.Default.formationLargeur * colonne) + (Properties.Settings.Default.largeurSeparation * colonne);
            formation.Top = Properties.Settings.Default.formationInitialX + (Properties.Settings.Default.formationHauteur * ligne) + (Properties.Settings.Default.largeurSeparation * ligne);
            formation.Width = Properties.Settings.Default.formationLargeur;
            formation.Height = Properties.Settings.Default.formationHauteur;
            formation.BackColor = Color.FromArgb(20, 0, 88, 117);

            // Ajout de la formation a la collection
            this.collectionFormation.Rows.Add(formation, idFormation);

            // Evenement dynamique acceptant des paramatre en plus
            container.Click += new EventHandler((sender, e) => formation_Click(sender, e, idFormation));
        }
        #endregion

        #region clics
        private void planningForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            Environment.Exit(0);
        }

        private void buttonCreaForm_Click(object sender, EventArgs e)
        {
            ajoutFormationForm form = new ajoutFormationForm(this);
            form.Show();
        }

        private void formation_Click(object sendser, EventArgs e, DateTime date)
        {
            choixFormationForm form = new choixFormationForm(date, this);
            form.Show();
        }
        private void label_Click(object sender, EventArgs e, DateTime date) 
        {
            String debut = date.ToString("yyyy-MM-dd 00:00:00:000");
            String fin = date.ToString("yyyy-MM-dd 23:59:59:999");

            // Récupère les formations du jour
            DataTable formations = SQL.requete("SELECT id_formation FROM formation WHERE debut_formation BETWEEN CONVERT(datetime, '" + debut + "', 21) " + "AND CONVERT(datetime, '" + fin + "',21);");
            int idFormation = (int)formations.Rows[0]["id_formation"];
            // Cas administrateur
            if (this.isAdmin)
            {
                ajoutFormationForm form = new ajoutFormationForm(idFormation, this);
                form.Show();

            }
            // Cas visiteur
            else if (isVisiteur)
            {
                inscriptionFormationForm form = new inscriptionFormationForm(idFormation);
                form.Show();
            }
            // Cas invité
            else
            {
                inscriptionFormationForm form = new inscriptionFormationForm(idFormation, this.infoConnexion);
                form.Show();
            }
            
        }

        // Methode gerant les action sur les formation selon le profil utilisateur
        private void formation_Click(object sendser, EventArgs e, int idFormation)
        {
            // Cas administrateur
            if (this.isAdmin)
            {
                ajoutFormationForm form = new ajoutFormationForm(idFormation, this);
                form.Show();

            }
            // Cas visiteur
            else if (isVisiteur)
            {
                inscriptionFormationForm form = new inscriptionFormationForm(idFormation);
                form.Show();
            }
            // Cas invité
            else
            {
                inscriptionFormationForm form = new inscriptionFormationForm(idFormation, this.infoConnexion);
                form.Show();
            }
        }

        // Methode permettant de changer le mois
        private void moisSuivant_Click(object sender, EventArgs e)
        {
            // On vide le calendrier
            this.cleanCalendar();
            // Si on à atteint décembre on change d'année
            if (labelMois.Text.Equals("Décembre"))
            {
                this.currentDate = new DateTime(this.currentDate.Year + 1, 1, 1);
                this.labelAnnee.Text = this.currentDate.Year.ToString();
            }
            else
            {
                this.currentDate = new DateTime(this.currentDate.Year, this.currentDate.Month + 1, 1);
            }

            // On redefini les info du nouveau mois
            this.nbJours = DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month);
            this.firstDay = new DateTime(this.currentDate.Year, this.currentDate.Month, 1);
            this.lastDay = new DateTime(this.currentDate.Year, this.currentDate.Month, DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month), 23, 59, 59, 999);

            this.labelMois.Text = moisAnnee[this.currentDate.Month - 1];

            generateCalendar(nbJours, this.firstDay, this.currentDate);
        }

        private void moisPrecedent_Click(object sender, EventArgs e)
        {
            // On vide le calendrier
            this.cleanCalendar();
            // Si on à atteint jamvier on change d'année
            if (labelMois.Text.Equals("Janvier"))
            {
                this.currentDate = new DateTime(this.currentDate.Year - 1, 12, 1);
                this.labelAnnee.Text = this.currentDate.Year.ToString();
            }
            else
            {
                this.currentDate = new DateTime(this.currentDate.Year, this.currentDate.Month - 1, 1);
            }

            // On redefini les info du nouveau mois
            this.nbJours = DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month);
            this.firstDay = new DateTime(this.currentDate.Year, this.currentDate.Month, 1);
            this.lastDay = new DateTime(this.currentDate.Year, this.currentDate.Month, DateTime.DaysInMonth(this.currentDate.Year, this.currentDate.Month), 23, 59, 59, 999);

            this.labelMois.Text = moisAnnee[this.currentDate.Month - 1];

            generateCalendar(nbJours, this.firstDay, this.currentDate);
        }
        #endregion
    }
}
